package com.example.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * `RedisTemplate` 是 Spring Data Redis 提供的一个工具类，用于在 Spring 项目中方便地操作 Redis。
 *  它是 Spring Data Redis 的核心类，封装了 Redis 的底层操作，使我们能够更方便地操作 Redis 的各种数据结构（String、Hash、List、Set、ZSet）。
 * 默认的 RedisTemplate<Object, Object> 序列化不友好
 * 自定义 redisTemplate() 可以：
 * 使用更通用的 StringRedisSerializer 或 Jackson2JsonRedisSerializer
 * 提高数据的可读性、互操作性
 * 控制 key 和 value 的序列化方式（比如 key 用字符串，value 用 JSON）
 */
@Configuration
public class RedisConfig {
    /**
     * 步骤	操作	                                        结果
     * ①	Spring Boot 启动时会尝试自动注入 redisTemplate	默认使用 JDK 序列化
     * ②	如果你自己写了一个 @Bean redisTemplate(...)	Spring Boot 放弃默认配置
     * ③	你写的 redisTemplate 被加入 IOC 容器	        可以直接 @Autowired 使用
     * ④	使用时直接通过 opsForXXX() 操作 Redis	        支持 JSON、字符串等序列化方式
     */
    /**
     * RedisConnectionFactory 是 Spring Data Redis 提供的 连接 Redis 的“工厂”接口，用来创建与 Redis 通信的连接（Connection）。
     * 它是 RedisTemplate 或 StringRedisTemplate 等底层 Redis 操作类的必要依赖，所有 Redis 命令的发送和接收，最终都要通过它来完成。
     *                 应用层
     *        ┌─────────────────────┐
     *        │     RedisTemplate   │ ← 你使用的工具类
     *        └─────────▲───────────┘
     *                  │ 依赖
     *        ┌─────────┴───────────┐
     *        │ RedisConnectionFactory │ ← Redis连接工厂接口
     *        └─────────▲───────────┘
     *                  │ 实现类
     *        ┌─────────┴───────────┐
     *        │ LettuceConnectionFactory │ ← 默认实现类（用Lettuce客户端）
     *        │ JedisConnectionFactory   │ ← 可选实现类（用Jedis客户端）
     *        └─────────────────────┘
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(factory);
        // 创建序列化工具
        /**
         * **序列化（Serialization）**是把 Java 对象 → 转换为字节流（byte[]）的过程，以便：
         * 存入磁盘（持久化）
         * 发送给网络另一端（传输）
         * 存到 Redis 这类支持二进制的数据库中
         * 反过来，从字节流 → 恢复为 Java 对象的过程叫反序列化（Deserialization）。
         *
         * Redis 只能存储字符串或二进制数据（byte[]），但 Java 中你用的是各种对象（String、List、Map、User 等），必须转成字节数组才能存进去。
         *
         * RedisSerializer<T> 是 Spring Data Redis 提供的序列化接口，用来定义：
         * Java 对象 → byte[] 的规则（写入 Redis）
         * byte[] → Java 对象 的规则（读取 Redis）
         */
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 初始化
        template.afterPropertiesSet();
        // 返回
        return template;
    }
}
/**
 * RedisTemplate 是你操作 Redis 的工具类，
 * 它依赖于 RedisConnectionFactory 来建立连接，
 * 并通过各种 RedisSerializer 实现 Java 对象与 Redis 数据的互相转换。
 */
